// ==UserScript==
// @name         JAVDB_影片预告
// @namespace    http://tampermonkey.net/
// @version      1.0.073
// @description  JAVDB自动显示预告片
// @author       A9
// @supportURL   https://sleazyfork.org/zh-CN/scripts/450740/feedback
// @source       https://github.com/bigwolf9987/JavBusTrailer
// @match        https://www.javbus.com/
// @include      /^https?:\/\/(?:[A-Za-z0-9]+\.)*(?:javdb[0-9]{3})(?:\.[A-Za-z0-9]+)?\/*/
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// @grant        GM_setClipboard
// @connect      r18.com
// @connect      dmm.co.jp
// @connect      javdb.com
// @connect      mgstage.com
// @connect      prestige-av.com
// @connect      javspyl.tk
// @connect      heyzo.com
// @connect      avfantasy.com
// @connect      tokyo-hot.com
// @connect      caribbeancom.com
// @connect      aventertainments.com
// @connect      10musume.com
// @connect      pacopacomama.com
// @connect      1pondo.tv
// @connect      cloudfront.net
// @icon         
// @require      https://fastly.jsdelivr.net/npm/video.js@7.10.2/dist/video.min.js
// @require      https://fastly.jsdelivr.net/npm/videojs-vr@1.10.1/dist/videojs-vr.min.js
// @require      https://fastly.jsdelivr.net/npm/dompurify@2.4.0/dist/purify.min.js
// @resource     video-js-css https://fastly.jsdelivr.net/npm/video.js@7.10.2/dist/video-js.min.css
// @resource     video-vr-js-css https://fastly.jsdelivr.net/npm/videojs-vr@1.10.1/dist/videojs-vr.css
// @license      MIT
// ==/UserScript==

(function () {
    "use strict";
    let player = null;
    //脚本设置项
    const settings = {
        enable_vr_mode: 1, //是否使用VR模式，0 关闭；1 开启
        enable_mute_play: 0, //是否开启静音播放，0 关闭；1 开启 （注：跨域页面无效，需手动控制播放与音量）
        video_playback_speed: 1.0, //视频默认播放速度，建议设置范围 0.25～2.0（注：数值越大播放速度越快）
        enable_debug_mode: 0,
        video_quality: 720, //视频清晰度,可设置为下列值之一：1080；720；480；360；240；（注：数值越大越清晰，所需网络加载时间越长）
    };
    // let postfixIndex = 0;
    // const postfixConnfig = {
    //     xxx: [{num: 2, prefix: "hhb"}, {num: 1, prefix: "mhb"}, {num: 0, prefix: "_dmb_w"}],
    //     miab: [{num: 0, prefix: "hhb"}],
    //     npjs: [{num: 0, prefix: "hhb"}],
    //     start: [{num: 0, prefix: "hhb"}],
    //     pred: [{num: 515, prefix: "mhb"}],
    //     dass: [{num: 200, prefix: "mhb"}, {num: 0, prefix: "_dmb_w"}],
    //     aege: [{num: 0, prenum: "", precorp: "1", prefix: "mhb"}],
    //     vec: [{num: 390, prenum: "00"}, {num: 0, prenum: ""}],
    //     shkd: [{num: 470, prefix: "_dmb_w"}, {num: 363, prefix: "_dmb_s"}, {num: 0, prenum: "", prefix: "_dmb_s"}],
    //     same: [{num: 0, prefix: "hhb"}],
    //     adn: [{num: 0, prefix: "hhb"}],
    //     rbk: [{num: 0, prefix: "hhb"}],
    //     atid: [{num: 0, prefix: "hhb"}],
    //     jbd: [{num: 0, prefix: "hhb"}],
    //     sspd: [{num: 0, prefix: "hhb"}],
    //     huntc: [{num: 0, prefix: "hhb"}],
    //     huntb: [{num: 0, prefix: "mhb"}],
    // };
    const postfixConnfig = {
        xxx: [{prefix: "hhb"}, {prefix: "mhb"}, {prefix: "_dmb_w"}],
        shkd: [{prefix: "_dmb_w"}, {prefix: "_dmb_s"}, {prenum: "", prefix: "_dmb_s"}],
        same: [{prefix: "hhb"}],
        adn: [{prefix: "hhb"}],
        rbk: [{prefix: "hhb"}],
        atid: [{prefix: "hhb"}],
        jbd: [{prefix: "hhb"}],
        sspd: [{prefix: "hhb"}],
        huntc: [{prefix: "hhb"}],
        huntb: [{prefix: "mhb"}],
        soan: [{prefix: "_dmb_w"}, {prenum: "", prefix: "mhb"}, { prenum: "00", prefix: "_mhb_w"}],
        venu: [{prenum: "", prefix: "_dmb_w"}, {prenum: "00", prefix: "_dmb_w"}, {prenum: "", prefix: "_sm_w"}],
		fset: [{prenum: "", prefix: "_dmb_w"}, {prenum: "00", prefix: "_dmb_w"}],
		aarm: [{prenum: "00", prefix: "mhb"}, {prenum: "", prefix: "_mhb_w"}],
		avop: [{prefix: "_dmb_w"}, {prenum: "", precorp: "1", prefix: "_dmb_w"}],
		dvaj: [{prenum: "00", prefix: "hhb"}, {prenum: "00", prefix: "mhb"}, {prenum: "", prefix: "hhb"}],
		ntr: [{prenum: "00", prefix: "_dmb_w"}, {prenum: "", prefix: "_dmb_w"}],
		vgd: [{prefix: "_dmb_w"}, {prefix: "_dmb_s"}],
		star: [{prefix: "_dmb_w"}, {prefix: "_sm_w"}, {prefix: "_dmb_s"}],
    };
    const corporations = {
        stars: ["1"],
        star: ["1"],
        svdvd: ["1"],
        sdde: ["1"],
        mogi: ["1"],
        dvdes: ["1"],
        fset: ["1"],
        rct: ["1"],
        wawa: ["1"],
        hawa: ["1"],
		sdnm: ["1"],
		dldss: ["1"],
		drpt: ["1"],
		dandy: ["1"],
        sw: ["1"],
		sdab: ["1"],
        sdjs: ["1"],
        sdmf: ["1"],
        sdmm: ["1"],
        sdmua: ["1"],
		piyo: ["1"],
        rctd: ["1"],
		fsdss: ["1"],
		sdmu: ["1"],
		sun: ["1"],
		kire: ["1"],
		aege: ["1"],
		wo: ["1"],
		sdth: ["1"],
		nhdtb: ["1"],
		nhdta: ["1"],
		hbad: ["1"],
		ftht: ["1", "00"],
		shh: ["1", "00"],
        shn: ["1", "00"],
		mtall: ["1", "00"],
        akdl: ["1", "00"],
		silkc: ["1", "00"],
		ntr: ["1", "00"],
		//
        abp: ["118"],
        abs: ["118"],
        ppt: ["118"],
		chn: ["118"],
		abw: ["118"],
		docp: ["118"],
		ftn: ["118"],
		//
		hgot: ["84"],
		mds: ["84"],
        scpx: ["84"],
        xrw: ["84"],
		gvg: ["13"],
		ovg: ["13"],
        jksr: ["57"],
        mcsr: ["57"],
        dv: ["53"],
		wkd: ["2", "00"],
        t28: ["55"],
        lol: ["12", "00"],
		dtvr: ["24", "00"],
		umd: ["125"],
		//
        awd: [""],
        apns: [""],
        dvaj: [""],
		vema: [""],
        venx: [""],
		hoks: [""],
        sqis: [""],
        real: [""],
        urkk: [""],
        bazx: [""],
        mdbk: [""],
        mdtm: [""],
        mkmp: [""],
        saba: [""],
        scop: [""],
		apaa: [""],
        ekdv: [""],
		aran: [""],
        aed: [""],
        anb: [""],
        cmv: [""],
		sinn: [""],
        hkd: [""],
        rvg: [""],
        scd: [""],
		gvh: [""],
        vec: [""],
        gma: [""],
        bobb: [""],
        focs: [""],
        tppn: [""],
        pkpd: [""],
        //aarm: [""],
        sqte: [""],
        flav: [""],
        jsop: [""],
        bda: [""],
		sora: [""],
        soan: [""],
		nsfs: ["", "00"],
        adn: ["", "00"],
		//
        hzgb: ["h_1100"],
		haru: ["h_687"],
        hz: ["h_113"],
        pym: ["h_283"],
        fone: ["h_491"],
		spz: ["h_254"],
        udak: ["h_254"],
        jukf: ["h_227"],
		rebd: ["h_346"],
		zex: ["h_720"],
		ofku: ["h_254"],
		supa: ["h_244"],
        tki: ["h_286"],
        nacr: ["h_237"],
        tmvi: ["h_452"],
		vgd: ["h_172"],
		mxgs: ["h_068"],
		//
		spro: ["h_1594", "00"],
        stcv: ["h_1616", "00"],
        skmj: ["h_1324"],
        fsvr: ["h_955", "00"],
        pydvr: ["h_1321", "00"],
        shind: ["h_1560", "00"],
        meko: ["h_1160", "00"],
        fgan: ["h_1440", "00"],
        fera: ["h_086", "00"],
        fuga: ["h_086", "00"],
        ktra: ["h_094", "00"],
        jrze: ["h_086", "00"],
        mesu: ["h_086", "00"],

    };
    const need_cors_domain = new Set(["smovie.1pondo.tv", "dy43ylo5q3vt8.cloudfront.net"]);
    DOMPurify.setConfig({
        KEEP_CONTENT: false,
        FORBID_ATTR: ["style"],
        FORBID_TAGS: ["img", "svg", "style"],
        RETURN_DOM: true,
    });

    //Start running from here
    const movieInfo = getMovieInfo();
    if (movieInfo?.movieId) {
        console.log("预告片番号信息 -----------------------" + movieInfo.movieId + "   有码=" + movieInfo.isEuropeOrAmerica);
        addButtonBottomList();
        
        addCiliButton();
        addMoivePreVideo();
    }
	addReimageButton();

    // 顶部按钮组
    addTopButtonList();

    // 列表增加预览按钮
    // addPreplayButtonList();


    // ******************************************************************************************************************************************************
    //#region Other

    /**
     * Append Video Player Element to Page
     * @param {object} movieInfo movieInfo
     * @returns
     */
    function addVideoPlayerElement(movieInfo) {
        debugger;
        if (!movieInfo.videoURL) return;
        let video;
        let muted = settings.enable_mute_play == true ? "muted" : "";
        //target video url need use iframe
        if (needCORS(movieInfo.videoURL)) {
            video = `
      <iframe id="preview-video-iframe" name="preview-video-iframe" width="60%" height="80%" style="border:none;border-radius:8px;" srcdoc="<html><head><style>*{width:100%;height:100%;padding:0;margin:0;overflow:hidden;} video{background: #000;}</style></head><body><video controls><source src='${movieInfo.videoURL}' type='video/mp4'></video></body></html>">
      </iframe>`;
        } else {
            video = `
        <video id="preview-video-player" playsinline controls preload="none" ${muted} poster="${
                document.querySelector("a.bigImage img")?.src
            }">
            <source src="${movieInfo.videoURL}" type="video/mp4" />
        </video>`;
            if (
                videojs &&
                ((settings.enable_vr_mode == true && movieInfo.isVR) ||
                    isM3U8(movieInfo.videoURL))
            ) {
                video = `
              <video id="preview-video-player" class="video-js" playsinline controls preload="none"
              ${muted} poster="${
                    document.querySelector("a.bigImage img")?.src
                }" crossorigin="anonymous">
              </video>`;
            }
        }
        let vContainer = document.createElement("div");
        vContainer.id = "preview-video-container";
        vContainer.innerHTML = video;

        //onclick event -- hide and pause player
        vContainer.addEventListener("click", (event) => {
            if (event?.target != vContainer) return;
            vContainer.style.display = "none";
            if (player) {
                player.pause();
            } else {
                //reset iframe to pause video
                if (needCORS(movieInfo.videoURL)) {
                    const iframe = document.querySelector("#preview-video-iframe");
                    let originIframe = iframe.cloneNode(true);
                    iframe.parentElement.append(originIframe);
                    iframe.remove();
                }
            }
            document.body.style.overflow = "auto";
        });
        document.body.append(vContainer);
        initVideoPlayer(movieInfo);
        addVideoPreviewImage();
    }

    function initVideoPlayer(movieInfo) {
        if (needCORS(movieInfo.videoURL)) {
            return;
        }
        if (
            videojs &&
            ((settings.enable_vr_mode == true && movieInfo.isVR) || isM3U8(movieInfo.videoURL))
        ) {
            player = videojs("preview-video-player", {
                playbackRates: [0.5, 1, 1.5, 2],
            });
            player.mediainfo = player.mediainfo || {};
            if (isM3U8(movieInfo.videoURL)) {
                player.src({
                    type: "application/x-mpegURL",
                    src: movieInfo.videoURL,
                });
            }
            //enabled vr plugin
            if (movieInfo.isVR) {
                player.src({
                    type: "video/mp4",
                    src: movieInfo.videoURL,
                });
                player.mediainfo.projection = "360";
                player.vr({ projection: "AUTO" });
                player.vr().on("initialized", () => {
                    player.vr().camera.position.x = -1.3981591081738982;
                    player.vr().camera.position.y = 0.035304011118944253;
                    player.vr().camera.position.z = -0.7904654323761686;
                });
                player.tech(false); //tech() will log warning without any argument
            }
            player.defaultPlaybackRate(settings.video_playback_speed);
        } else {
            player = document.querySelector("#preview-video-player");
            player.playbackRate = settings.video_playback_speed;
        }
    }

    /**
     * Append video preview image to movie gallery
     * @returns
     */
    function addVideoPreviewImage() {
        let imgWaterFall = document.querySelector("#sample-waterfall");
        if (!imgWaterFall) {
            imgWaterFall = document.createElement("div");
            imgWaterFall.id = "sample-waterfall";
            let heading = document.createElement("h4");
            heading.innerText = "樣品圖像";
            const clearfix = document.getElementsByClassName("clearfix")[0];
            clearfix?.before(heading, imgWaterFall);
        }
        let previewImgSpan = document.createElement("span");
        previewImgSpan.classList.add("sample-box");
        let photoFrame = document.createElement("div");
        photoFrame.classList.add("photo-frame", "preview-video-img-container");
        let posterImg = document.querySelector("a.bigImage img");
        if (posterImg) {
            let img = document.createElement("img");
            img.src = posterImg.src;
            photoFrame.append(img);
        }
        previewImgSpan.append(photoFrame);
        imgWaterFall.prepend(previewImgSpan);

        //onclick event
        previewImgSpan.addEventListener("click", () => {
            let vContainer = document.querySelector("#preview-video-container");
            if (vContainer) {
                document.body.style.overflow = "hidden";
                vContainer.style.display = "flex";
                if (player) {
                    player.pause();
                    player.load();
                    player.play();
                    player.focus();
                }
            }
        });
    }

    //#endregion

    //#region VideoUrl
    // function getPostfixItem(postfixIndex) {
    //     let prefixArr = postfixConnfig["xxx"];
    //     var confg = prefixArr[postfixIndex];
    //
    //     return confg.prefix;
    // }
    //
    // function changePostfixItem(postfixIndex){
    //     postfixIndex++;
    //     if(postfixIndex >= 3) {
    //         postfixIndex = 0;
    //     }
    //
    //     return postfixIndex;
    // }

    async function getVideoURL_2(movieInfo) {
        let videoURL = await queryLocalCacheDB(movieInfo)
            .catch((e) => {
                log(e);
                return queryDMMVideoURL(movieInfo, undefined, true, 0);
            })
            .catch((e) => {
                log(e);
                //changePostfixItem();
                return queryDMMVideoURL(movieInfo, undefined, true, 1);
            })
            .catch((e) => {
                log(e);
                //changePostfixItem();
                return queryDMMVideoURL(movieInfo, undefined, true, 2);
            })
            .catch((e) => {
                log(e);
            });
        movieInfo.videoURL = convertHTTPToHTTPS(videoURL);
        return movieInfo;
    }

    async function getVideoURL(movieInfo) {
        let videoURL = await queryLocalCacheDB(movieInfo)
            .catch((e) => {
                log(e);
                return queryDMMVideoURL(movieInfo);
            })
            .catch((e) => {
                log(e);
                return queryDMMVideoURL(movieInfo, undefined, true);
            })
            .catch((e) => {
                log(e);
                return queryJavSpylVideoURL(movieInfo);
            })
            .catch((e) => {
                log(e);
                return queryPrestigeVideoURL(movieInfo);
            })
            .catch((e) => {
                log(e);
                return queryMGStageVideoURL(movieInfo);
            })
            .catch((e) => {
                log(e);
                //retry query (use movie title as keyword)
                return queryMGStageVideoURL(movieInfo, true);
            })
            .catch((e) => {
                log(e);
                return queryBasicUncensoredVideoURL(movieInfo);
            })
            .catch((e) => {
                log(e);
                return queryTokyoHotVideoURL(movieInfo);
            })
            .catch((e) => {
                log(e);
                return queryAVFantasyVideoURL(movieInfo);
            })
            .catch((e) => {
                log(e);
                return queryAVFantasyVideoURL(movieInfo, true);
            })
            // .catch((e) => {
            //   log(e);
            //   return queryJavDBVideoURL(movieInfo);
            // })
            .catch((e) => {
                log(e);
            });
        movieInfo.videoURL = convertHTTPToHTTPS(videoURL);
        return movieInfo;
    }

    async function queryBasicUncensoredVideoURL(movieInfo) {
        if (!movieInfo.isUncensored)
            return Promise.reject(
                "Query basic uncensored: This function only support uncensored movie."
            );
        let videoURLs;
        const qualityArr = ["720p.mp4", "1080p.mp4", "480p.mp4", "360p.mp4", "240p.mp4"];
        if (
            movieInfo.corpName === "カリビアンコム" ||
            movieInfo.corpName === "Caribbeancom"
        ) {
            //create different quality video urls.
            videoURLs = qualityArr.map(
                (quality) =>
                    `https://smovie.caribbeancom.com/sample/movies/${movieInfo.movieId}/${quality}`
            );
        } else if (movieInfo.corpName === "東京熱" || movieInfo.corpName === "TokyoHot") {
            videoURLs = [`https://my.cdn.tokyo-hot.com/media/samples/${movieInfo.movieId}.mp4`];
        } else if (movieInfo.corpName === "天然むすめ" || movieInfo.corpName === "10musume") {
            videoURLs = qualityArr.map(
                (quality) =>
                    `https://smovie.10musume.com/sample/movies/${movieInfo.movieId}/${quality}`
            );
        } else if (movieInfo.corpName === "一本道" || movieInfo.corpName === "1pondo") {
            videoURLs = qualityArr.map(
                (quality) =>
                    `https://smovie.1pondo.tv/sample/movies/${movieInfo.movieId}/${quality}`
            );
            videoURLs.push(
                `https://ppvclips02.aventertainments.com/01m3u8/1pon_${movieInfo.movieId}/1pon_${movieInfo.movieId}.m3u8`
            );
        } else if (
            movieInfo.corpName === "ワンピース" ||
            movieInfo.corpName === "オリエンタルドリーム" ||
            movieInfo.corpName === "OnePieceEntertainment" ||
            movieInfo.corpName === "OrientalDream"
        ) {
            videoURLs = [
                `https://ppvclips02.aventertainments.com/${movieInfo.movieId}/ts/${movieInfo.movieId}-m3u8-aapl.ism/manifest(format=m3u8-aapl).m3u8`,
            ];
        } else if (
            movieInfo.corpName === "パコパコママ" ||
            movieInfo.corpName === "pacopacomama"
        ) {
            videoURLs = qualityArr.map(
                (quality) =>
                    `https://fms.pacopacomama.com/hls/sample/pacopacomama.com/${movieInfo.movieId}/${quality}`
            );
        } else {
            return Promise.reject(
                "Query basic uncensored: This function not support this corporation movie."
            );
        }
        for (const videoURL of videoURLs) {
            log("Query basic uncensored:\r\n" + videoURL);
            const validatedURL = await xFetch(videoURL, { method: "head" })
                .then((resp) => {
                    if (resp?.status === 200) {
                        log("Query basic uncensored: server result video url: " + videoURL);
                        return videoURL;
                    }
                    return null;
                })
                .catch((e) => {
                    log(e);
                    return null;
                });
            if (validatedURL) {
                return Promise.resolve(validatedURL);
            }
        }
        return Promise.reject("Query basic uncensored: Not found movie.");
    }

    async function queryJavSpylVideoURL(movieInfo) {
        //Video links for these companies require cors, so ignore it.
        // if (
        //   movieInfo.corpName === "HEYZO" ||
        //   movieInfo.corpName === "一本道" ||
        //   movieInfo.corpName === "1pondo"
        // ) {
        //   return Promise.reject("JavSpyl server not support this corporation movie.");
        // }
        //see https://bit.ly/3RkgqSo
        let serverURL = "https://v2.javspyl.tk/api/";
        return await xFetch(serverURL, {
            headers: {
                origin: "https://v2.javspyl.tk",
                "Content-Type": "application/x-www-form-urlencoded",
            },
            data: `ID=${movieInfo.movieId}`,
            method: "POST",
        })
            .then((resp) => {
                return JSON.parse(resp.responseText);
            })
            .then((video) => {
                if (video?.info?.url?.length > 0) {
                    log("JavSpyl server result video url: https://" + video.info.url);
                    return "https://" + video.info.url;
                } else {
                    return Promise.reject("JavSpyl server not found movie.");
                }
            })
            .catch((e) => {
                return Promise.reject(e);
            });
    }

    async function queryAVFantasyVideoURL(movieInfo, isStandbyServer = false) {
        if (!movieInfo.isUncensored)
            return Promise.reject("AVFantasyDMM server only support uncensored movie.");
        let notFound = Promise.reject("AVFantasy server not found movie.");
        let keyword = movieInfo.movieId;
        //Movie codes for these companies are not supported, so use movie titles to search.
        if (movieInfo.corpName === "HEYZO") {
            keyword = movieInfo.titleKeyPhrase;
        }
        let serverURL = `https://www.avfantasy.com/ppv/ppv_searchproducts.aspx?keyword=${keyword}`;
        if (isStandbyServer) {
            serverURL = `https://www.avfantasy.com/search_Products.aspx?keyword=${keyword}`;
        }
        log("AVFantasyDMM server query:\r\n" + serverURL);
        return await xFetch(serverURL)
            .then((response) => {
                //AVFantasy search result, may contain multiple movies.
                let doc = convertTextToDOM(response.responseText);
                let resultMovies = doc.querySelectorAll(".single-slider-product");
                if (!resultMovies) return notFound;
                let targetMovieEle = null;
                for (const element of resultMovies.values()) {
                    if (matchMovieByKeyword(element.innerHTML, movieInfo)) {
                        targetMovieEle = element;
                        break;
                    }
                }
                if (!targetMovieEle) return notFound;
                let movieDetailPathName = targetMovieEle.querySelector("a")?.href;
                if (!movieDetailPathName) return notFound;
                return xFetch(movieDetailPathName);
            })
            .then((response) => {
                //AVFantasy movie detail page result.
                let doc = convertTextToDOM(response.responseText);
                let videoSource = doc.querySelector("video source");
                if (videoSource && videoSource?.src) {
                    log("AVFantasy server result video url: " + videoSource.src);
                    return videoSource.src;
                }
                return notFound;
            })
            .catch((e) => {
                return Promise.reject(e);
            });
    }

    async function queryJavDBVideoURL(movieInfo) {
        let serverURL = `https://javdb.com/search?q=${movieInfo.movieId}&f=all`;
        let notFound = Promise.reject("JavDB server not found movie.");
        log("JavDB server query:\r\n" + serverURL);
        return await fetch(serverURL)
            .then((resp) => {
                return resp.text();
            })
            .then((text) => {
                //JavDB search result, may contain multiple movies.
                let doc = convertTextToDOM(text);
                let resultMovies = doc.querySelectorAll(".item");
                let targetMovieEle = null;
                for (const element of resultMovies.values()) {
                    if (matchMovieByKeyword(element.innerHTML, movieInfo)) {
                        targetMovieEle = element;
                        break;
                    }
                }
                if (!targetMovieEle) return notFound;
                let avDetailPathName = targetMovieEle.querySelector("a")?.pathname;
                if (!avDetailPathName) return notFound;
                return fetch("https://javdb.com" + avDetailPathName);
            })
            .then((avDetailResp) => {
                return avDetailResp.text();
            })
            .then((text) => {
                //JavDB movie detail page result.
                let doc = convertTextToDOM(text);
                let videoSource = doc.querySelector("#preview-video source");
                if (videoSource && videoSource?.src && videoSource.src != location.href) {
                    log("JavDB server result video url: " + videoSource.src);
                    return videoSource.src;
                }
                return notFound;
            })
            .catch((e) => {
                return Promise.reject(e);
            });
    }

    async function queryDMMVideoURL(
        movieInfo,
        host = "cc3001.dmm.co.jp",
        hasPrefix = false,
        prefixIndex = 0
    ) {
        if (movieInfo.isUncensored)
            return Promise.reject("DMM server not support uncensored movie.");
        if (movieInfo.thumbnailURL?.includes("mgstage.com"))
            return Promise.reject("DMM server not support MGStage movie.");
        //see https://www.javbus.com/forum/forum.php?mod=viewthread&tid=63374
        //see https://bit.ly/3wXLj6T
        let infix = "litevideo/freepv";
        //1500kbps = _dmb_w || 3000kbps = _mhb_w || vrlite || _sm_w.mp4 || _dm_w.mp4 || _dmb_s.mp4!!
        let postfix = "_dmb_w";
        if (movieInfo.isVR) {
            postfix = "vrlite";
            infix = "vrsample";
        }

        let movieIdSplit = movieInfo.movieId.toLowerCase().split("-");
        let corp = movieIdSplit[0];
        let idNum = movieIdSplit[1];

        let videoURL = `https://${host}/${infix}/${corp[0]}/${corp.substring(
            0,
            3
        )}/${corp}${idNum}/${corp}${idNum}${postfix}.mp4`;

        if (hasPrefix === false && movieInfo.thumbnailURL?.includes("pics.dmm.co.jp")) {
            //extract keyword from thumbnail
            //example: https://pics.dmm.co.jp/digital/video/mkmp00497/mkmp00497jp-2.jpg
            //result keyword: mkmp00497
            let keywordFromThumbnail = movieInfo.thumbnailURL
                ?.split("video/")[1]
                ?.split("/")[0];
            //validation
            if (keywordFromThumbnail?.includes(corp) && keywordFromThumbnail?.includes(idNum)) {
                videoURL = `https://${host}/${infix}/${
                    keywordFromThumbnail[0]
                }/${keywordFromThumbnail.substring(
                    0,
                    3
                )}/${keywordFromThumbnail}/${keywordFromThumbnail}${postfix}.mp4`;
            }
        }

        if (hasPrefix === true) {
            var preNum = "";
            var preCorp = "";

            if (corporations[corp]) {
                //There must first get the idNum, and then get corp. Because corp will change.
                preNum = corporations[corp][1] ? corporations[corp][1] : "";
                preCorp = corporations[corp][0];
            } else {
                //if last time query is fail, this time try to add '00' prefix
                if (!movieInfo.thumbnailURL?.includes("pics.dmm.co.jp")) {
                    preNum = "00";
                }
            }

            if (postfixConnfig[corp]) {
                if (postfixConnfig[corp][prefixIndex]) {
                    var confg = postfixConnfig[corp][prefixIndex];
                    // if (confg.num <= parseInt(idNum)){
                    //     if (confg.prefix != null){
                    //         postfix = confg.prefix;
                    //     }
                    //
                    //     if (confg.prenum != null){
                    //         preNum = confg.prenum;
                    //     }
                    //
                    //     if (confg.precorp != null){
                    //         preCorp = confg.precorp;
                    //     }
                    //
                    // }else {
                    //     return Promise.reject("num not pipei.");
                    // }

                    if (confg.prefix != null) {
                        postfix = confg.prefix;
                    }

                    if (confg.prenum != null) {
                        preNum = confg.prenum;
                    }

                    if (confg.precorp != null){
                        preCorp = confg.precorp;
                    }
                } else {
                    return Promise.reject("prefixIndex is empty.");
                }
            }else if (postfixConnfig["xxx"]){
                if (postfixConnfig["xxx"][prefixIndex]) {
                    var confg = postfixConnfig["xxx"][prefixIndex];
                    if (confg.prefix != null) {
                        postfix = confg.prefix;
                    }
                }
            }else if (prefixIndex > 0){
                return Promise.reject("postfixConnfig is empty.");
            }

            idNum = preNum + idNum;
            corp = preCorp + corp;
            videoURL = `https://${host}/${infix}/${corp[0]}/${corp.substring(
                0,
                3
            )}/${corp}${idNum}/${corp}${idNum}${postfix}.mp4`;
        }

        log("DMM server query:\r\n" + videoURL);

        return await fetch(videoURL, {
            method: "head",
            referrerPolicy: "no-referrer",
        })
            .then((resp) => {
                if (resp.ok) {
                    log("DMM server result video url: " + videoURL);
                    GM_setValue(movieInfo.movieId, videoURL);
                    return videoURL;
                } else {
                    return Promise.reject("DMM server not found movie.");
                }
            })
            .catch((e) => {
                return Promise.reject(e);
            });
    }

    async function queryMGStageVideoURL(movieInfo, isUseTitle = false) {
        if (
            movieInfo.isUncensored ||
            (movieInfo.corpName.includes("プレステージ") === false &&
                movieInfo.corpName.includes("ラグジュTV") === false &&
                movieInfo.corpName.toUpperCase().includes("PRESTIGE") === false &&
                !movieInfo.thumbnailURL?.includes("mgstage.com") &&
                !movieInfo.thumbnailURL?.includes("prestige-av.com"))
        )
            return Promise.reject(
                `MGStage server not support movieId: ${movieInfo.movieId}, CorpName: ${movieInfo.corpName}`
            );
        let notFound = () => Promise.reject("MGStage server not found movie.");
        //Need ladder
        let keyword = isUseTitle ? movieInfo.titleKeyPhrase : movieInfo.movieId;
        let serverURL = `https://www.mgstage.com/search/cSearch.php?search_word=${keyword}&list_cnt=30`;
        log("MGStage server query:\r\n" + serverURL);
        return await xFetch(serverURL)
            .then((resp) => {
                //MGStage search result, may contain multiple movies.
                let doc = convertTextToDOM(resp.responseText);
                let resultMovies = doc.querySelectorAll(".rank_list li");
                let targetMovieEle = null;
                for (const element of resultMovies.values()) {
                    if (matchMovieByKeyword(element.innerHTML, movieInfo)) {
                        targetMovieEle = element;
                        break;
                    }
                }
                if (!targetMovieEle) return notFound();
                let avDetailPathName = targetMovieEle.querySelector(".button_sample")?.pathname;
                if (!avDetailPathName) return notFound();
                let pid = avDetailPathName.split("/").at(-1);
                return xFetch(
                    "https://www.mgstage.com/sampleplayer/sampleRespons.php?pid=" + pid
                );
            })
            .then((avDetailResp) => {
                //MGStage movie detail page result.
                let videoURL = JSON.parse(avDetailResp.response)?.url?.split(".ism")[0] + ".mp4";
                if (videoURL) {
                    log("MGStage server result video url: " + videoURL);
                    return videoURL;
                }
                return notFound();
            })
            .catch((e) => {
                return Promise.reject(e);
            });
    }

    async function queryPrestigeVideoURL(movieInfo, isUseTitle = false) {
        if (
            movieInfo.isUncensored ||
            (movieInfo.corpName.includes("プレステージ") === false &&
                movieInfo.corpName.toUpperCase().includes("PRESTIGE") === false &&
                !movieInfo.thumbnailURL?.includes("mgstage.com") &&
                !movieInfo.thumbnailURL?.includes("prestige-av.com"))
        )
            return Promise.reject(
                `Prestige server not support movieId: ${movieInfo.movieId}, CorpName: ${movieInfo.corpName}`
            );
        let notFound = () => Promise.reject("Prestige server not found movie.");
        //Need ladder
        let keyword = isUseTitle ? movieInfo.titleKeyPhrase : movieInfo.movieId;
        let serverURL = `https://www.prestige-av.com/api/search?isEnabledQuery=true&searchText=${keyword}&isEnableAggregation=false&release=false&reservation=false&soldOut=false&from=0&aggregationTermsSize=0&size=20`;
        log("Prestige server query:\r\n" + serverURL);
        return await xFetch(serverURL)
            .then((avDetailResp) => {
                let resultMovies = JSON.parse(avDetailResp.response)?.hits?.hits;
                for (const movieDetail of resultMovies) {
                    let { deliveryItemId, productTitle, productMovie } = movieDetail["_source"];
                    if (
                        matchMovieByKeyword(deliveryItemId + productTitle, movieInfo) &&
                        productMovie?.path
                    ) {
                        let videoURL = "https://www.prestige-av.com/api/media/" + productMovie.path;
                        log("Prestige server result video url: " + videoURL);
                        return videoURL;
                    }
                }
                return notFound();
            })
            .catch((e) => {
                return Promise.reject(e);
            });
    }

    async function queryTokyoHotVideoURL(movieInfo) {
        if (
            !movieInfo.isUncensored ||
            (movieInfo.corpName != "東京熱" && movieInfo.corpName.toUpperCase() != "TOKYOHOT")
        )
            return Promise.reject(
                `TokyoHot server not support movieId: ${movieInfo.movieId}, CorpName: ${movieInfo.corpName}`
            );
        let notFound = Promise.reject("TokyoHot server not found movie.");
        //Need ladder
        let serverURL = `https://my.cdn.tokyo-hot.com/product/?q=${movieInfo.movieId}`;
        log("TokyoHot server query:\r\n" + serverURL);
        return await xFetch(serverURL)
            .then((resp) => {
                //search result, may contain multiple movies.
                let doc = convertTextToDOM(resp.responseText);
                let resultMovies = doc.querySelectorAll(".list.slider.cf li");
                let targetMovieEle = null;
                for (const element of resultMovies.values()) {
                    if (matchMovieByKeyword(element.innerHTML, movieInfo)) {
                        targetMovieEle = element;
                        break;
                    }
                }
                if (!targetMovieEle) return notFound;
                let avDetailPathName = targetMovieEle.querySelector(".rm")?.pathname;
                if (!avDetailPathName) return notFound;
                return xFetch("https://my.cdn.tokyo-hot.com/" + avDetailPathName);
            })
            .then((resp) => {
                //detail page result
                let doc = convertTextToDOM(resp.responseText);
                let videoSource = doc.querySelector("video source");
                if (videoSource && videoSource?.src && videoSource.src != location.href) {
                    log("Tokyo server result video url: " + videoSource.src);
                    return videoSource.src;
                }
                return notFound;
            })
            .catch((e) => {
                return Promise.reject(e);
            });
    }

    async function queryLocalCacheDB(movieInfo) {
        let videoSource = GM_getValue(movieInfo.movieId, null);
        if (!videoSource) {
            return Promise.reject("Local cache storage not found movie.");
        }

        return Promise.resolve(videoSource);

        // return await xFetch(videoSource, { method: "head" })
        //     .then((resp) => {
        //         if (resp?.status === 200) {
        //             log("The video source URL validate successful. Video source: " + videoSource);
        //             return Promise.resolve(videoSource);
        //         }
        //         //If validation fails,remove the url from the local cache.
        //         GM_deleteValue(movieInfo.movieId);
        //         return Promise.reject("The video source URL validate failed. Not found movie.");
        //     })
        //     .catch((e) => {
        //         return Promise.reject(e);
        //     });
    }

    //#endregion

    //#region Utility

    async function xFetch(url, fetchInit = {}) {
        const defaultFetchInit = { method: "get" };
        const { headers, method, data } = { ...defaultFetchInit, ...fetchInit };
        return new Promise((resolve, reject) => {
            void GM_xmlhttpRequest({
                url,
                method,
                headers,
                data,
                onerror: reject,
                onload: async (response) => resolve(response),
            });
        });
    }

    function convertTextToDOM(text) {
        return DOMPurify.sanitize(text);
    }

    function log(msg) {
        if (settings.enable_debug_mode == true) {
            if (typeof msg === "object") {
                console.dir(msg);
            } else {
                console.log(msg);
            }
        }
    }

    function isM3U8(url) {
        return url?.endsWith("m3u8");
    }

    function needCORS(url) {
        return need_cors_domain.has(new URL(url)?.host);
    }

    /**
     * Convert HTTP protocol to HTTPS protocol
     * @param {string} url
     * @returns {string} url
     */
    function convertHTTPToHTTPS(url) {
        if (url?.startsWith("http:")) {
            return url.replace("http:", "https:");
        }
        return url;
    }

    function matchMovieByKeyword(str, movieInfo) {
        if (str.indexOf(movieInfo.movieId) != -1 || str.indexOf(movieInfo.title) != -1) {
            return true;
        }
        if (str.indexOf(movieInfo.titleKeyPhrase) != -1) {
            return true;
        }
        if (findDifference(movieInfo.titleKeyPhrase, removeWhitespace(str)).length < 4) {
            return true;
        }
        return false;
    }

    function getKeyPhrase(str, splitChar = " ") {
        return str
            .split(splitChar)
            .reduce((pre, cur) => (cur?.length > pre.length ? cur : pre), "");
    }

    function findDifference(str1, str2) {
        const len = Math.min(str1.length, str2.length);
        const result = [];
        for (let i = 0; i < len; i++) {
            if (str1[i] !== str2[i]) {
                result.push(str1[i]);
                str1 = replaceChar(str1, i, str2[i]);
            }
        }
        return result;
    }

    function replaceChar(str, index, newChar) {
        const leftPart = str.slice(0, index);
        const rightPart = str.slice(index + 1);
        return leftPart + newChar + rightPart;
    }

    function removeWhitespace(str) {
        return str.replace(/\s/g, "");
    }

    //#endregion

    // ******************************************************************************************************************************************************
    //#region Common

    function updateVideoAddrElement(pre_id, movieInfo) {
        var addr_id = "#" + pre_id + "_" + movieInfo.movieId;
        var addr = document.querySelector(addr_id);
        if (addr){
            addr.href = movieInfo.videoURL;
            addr.textContent = movieInfo.videoURL;
        }
    }

    async function copyTextToClipboard(text) {
        try {
            await navigator.clipboard.writeText(text);
            console.log('-------复制成功！！！！！！！！！');
        } catch (err) {
            console.error('-------复制失败: ', err);
        }
    }

    function getMovieInfo() {
        const infoDom = document.querySelector(".movie-panel-info");
        if (!infoDom) {
            console.log("getMovieInfo -------------- 失败!!!!");
            return;
        }
        let movieId = infoDom.innerText
            .match(/[A-Za-z]{2,5}-\d{2,5}/)
            ?.at(0);
        let corpName = infoDom.innerText
            .match(/(?<=(?:片商|Maker):.)[\x20\S]+/)
            ?.at(0)
            ?.trim();
        let isVR =
            infoDom
                .querySelector("#genre-toggle")
                ?.parentElement?.nextElementSibling.innerText.search(
                /ハイクオリティVR|VR専用|カリVR|VR/
            ) > -1;
        let isUncensored =
            document
                .querySelector("#navbar li.active")
                ?.innerText.search(/無碼|Uncensored|無修正|무수정/) > -1;
        let isEuropeOrAmerica =
            document
                .querySelector("#navbar li.active")
                ?.innerText.search(/歐美|Western|外国人|서양의/) > -1;
        let title = document.querySelector(".current-title")?.innerText;
        let thumbnailURL = document.querySelector(".sample-box")?.href;
        let titleKeyPhrase = getKeyPhrase(title);
        let videoURL = "www";
        let isPlay = false;

        //retry extract
        if (titleKeyPhrase === title) titleKeyPhrase = getKeyPhrase(title, "！！");

        log({
            title,
            movieId,
            corpName,
            isVR,
            isUncensored,
            isEuropeOrAmerica,
            thumbnailURL,
            titleKeyPhrase,
            videoURL,
            isPlay
        });
        return {
            title,
            movieId,
            corpName,
            isVR,
            isUncensored,
            isEuropeOrAmerica,
            thumbnailURL,
            titleKeyPhrase,
            videoURL,
            isPlay
        };
    }

    /**
     * Append player style
     */
    function addPreviewVideoStyle() {
        let containerStyle = `
        #preview-video-container{
            position: fixed;
            height: 100%;
            width: 100%;
            background-color: rgba(0,0,0,0.8);
            top: 0px;
            z-index: 999;
            display: none;
            align-items: center;
            justify-content: center;
        }
        #preview-video-container:before {
            content: '\\2715';
            font-size: 28px;
            color: white;
            opacity: 0.7;
            right: 18px;
            top: 8px;
            position: absolute;
            cursor: pointer;
            pointer-events:none;
        }
        #preview-video-player{
            height: 80%;
            min-width: 70%;
            max-width: 80%;
            background-color: #000;
            border-radius: 8px;
            outline: none;
            overflow: hidden;
        }
        .preview-video-img-container{
            position: relative;
            cursor:pointer;
        }
        .preview-video-img-container img{
            max-width: 100%;
            object-fit: cover;
            width: 120px;
        }
        .preview-video-img-container:after {
            background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'  viewBox='0 0 512 512'%3E%3Cpath d='M448 255c0-106-86-192-192-192S64 150 64 256s86 192 192 192 192-86 192-192z' fill='gold'  fill-opacity='0.8' stroke='none'/%3E%3Cpath fill='white' d='M216.32  334.44l114.45-69.14a10.89 10.89 0 000-18.6l-114.45-69.14a10.78 10.78 0 00-16.32 9.31v138.26a10.78 10.78 0 0016.32 9.31z'/%3E%3C/svg%3E");
            background-repeat: no-repeat;
            background-position: 50%;
            background-color: #0000005e;
            background-size: 48px 48px;
            bottom: 0;
            content: "";
            display: block;
            left: 0;
            position: absolute;
            right: 0;
            top: 0;
        }
        `;
        GM_addStyle(containerStyle);
        GM_addStyle(GM_getResourceText("video-js-css"));
        GM_addStyle(GM_getResourceText("video-vr-js-css"));
    }

    function createMovieInfo() {

        let movieId = "DVDES-101";
        let corpName = "unknown";
        let isVR =  false;
        let isUncensored = false;
        let isEuropeOrAmerica = false;
        let title = "unknown";
        let thumbnailURL = "unknown";
        let titleKeyPhrase = "unknown";
        let videoURL = "http://xxx/";
        let webURL = "http://xxx/";

        // log({
        //     title,
        //     movieId,
        //     corpName,
        //     isVR,
        //     isUncensored,
        //     isEuropeOrAmerica,
        //     thumbnailURL,
        //     titleKeyPhrase,
        // });
        return {
            title,
            movieId,
            corpName,
            isVR,
            isUncensored,
            isEuropeOrAmerica,
            thumbnailURL,
            titleKeyPhrase,
            videoURL,
            webURL
        };
    }

    function loadMovieInfo(){
        // document.getElementById("demo").innerHTML=Date();

        const movieInfo = getMovieInfo();
        if (movieInfo?.movieId) {
            let movieIdSplit = movieInfo.movieId.toLowerCase().split("-");
            let corp = movieIdSplit[0];
            let idNum = movieIdSplit[1];
            let num = parseInt(idNum);

            document.getElementById("movieId-corp").value = corp;
            document.getElementById("movieId-start").value = num - 10;
            document.getElementById("movieId-end").value = num;

        }
    }

    function padNumber(num, size) {
        var s = num+""; // 将数字转换为字符串
        while (s.length < size) s = "0" + s; // 如果字符串长度小于指定大小，则在前面添加0
        return s;
    }

    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    function concatenateChineseCharacters(str) {
        let strArr = str.split(" ");
        // 使用正则表达式匹配汉字
        // 这里只考虑了基本汉字范围\u4e00-\u9fa5
        const chineseCharsRegex = /[\u4e00-\u9fa50-9A-Zの=]+/g;

        // 使用matchAll方法（注意：在某些旧版JavaScript环境中可能需要polyfill或使用match然后处理结果）
        // matchAll返回一个迭代器，包含所有匹配项及其相关信息
        const matches = [...strArr[0].matchAll(chineseCharsRegex)];

        // 遍历匹配项，并提取出匹配的汉字字符串
        // 由于我们使用的是+量词，每个匹配项都是一个或多个连续的汉字
        let concatenatedChinese = '';
        // matches.forEach(match => {
        //     concatenatedChinese += "、" + match[0]; // match[0]是匹配的整个字符串
        // });
        for (let i=0; i<matches.length; i++){
            if (i == 0){
                concatenatedChinese += matches.at(i)[0]; // match[0]是匹配的整个字符串
            }else {
                concatenatedChinese += "、" + matches.at(i)[0]; // match[0]是匹配的整个字符串
            }
        }
        concatenatedChinese += "=" + strArr[1];

        return concatenatedChinese;
    }

    function concatenateChineseCharacters_2(str) {
        // let strArr = str.trim().split(' ');

        const regex = /[\s,!?、，！？」】●]+/g;
        let strArr2 = str.trim().split(regex);

        let concatenatedChinese = '';
        if (strArr2.length > 0){
            concatenatedChinese += strArr2[0].trim();
        }

        // if (strArr.length >= 2){
        //     concatenatedChinese += "==" + strArr[strArr.length - 1];
        // }

        return concatenatedChinese;
    }

    function parseYanYuan(yanYuanStr){
        let yanYanArr = yanYuanStr.trim().split(' ');
        let nvYanYuan = '';

        for (let i=0; i < yanYanArr.length; i++){
            let yan = yanYanArr[i];

            if (yan.lastIndexOf('♀') >= 0){
                let re = (i == 0)? '==' : '、';
                nvYanYuan += re + yan.replace('♀', '').trim();
            }
        }

        return nvYanYuan;
    }

    // 定义一个函数来获取选择的文本
    function getSelectedText() {
        // 使用window.getSelection()获取Selection对象
        const selection = window.getSelection();

        // 检查是否有选择的文本
        if (selection.rangeCount > 0) {
            // 获取第一个（也可能是唯一的）Range对象
            const range = selection.getRangeAt(0);

            // 使用Range对象的toString方法获取选择的文本
            // 注意：这里假设选择的是纯文本，没有包含其他元素或富文本格式
            const selectedText = range.toString();

            // 返回选择的文本
            return selectedText;
        }

        // 如果没有选择的文本，返回null或空字符串
        return null; // 或者 return '';
    }
	
	function popupWindow(newUrl, width = 1420, height = 960){
        var left = (window.screen.width - width)/2;
        var top = (window.screen.height - height)/2;
        var popupWindow = window.open(newUrl, '_blank', `left=${left}, top=${top} width=${width}, height=${height}`);
        // popupWindow.location.href = newUrl;
    }

    //#endregion

    // ******************************************************************************************************************************************************
    //#region 主页-预告video
    function createVideoCss(){
        // 创建一个新的<style>元素
        const style = document.createElement('style');
        style.type = 'text/css';

        // 添加CSS规则到<style>元素中
        const cssRules = `
      .box .cover video {
            z-index: 0;
            transition: transform .2s ease;
            position: absolute;
            top: 0;
            left: 0;
            height: 100%;
            /*-o-object-position: 50% 50%;*/
            /*object-position: 50% 50%;*/
        }
    `;

        if (style.styleSheet) {
            // 对于IE
            style.styleSheet.cssText = cssRules;
        } else {
            // 其他浏览器
            style.appendChild(document.createTextNode(cssRules));
        }

// 将<style>元素添加到文档的<head>中
        document.head.appendChild(style);
    }
    function initVideoList(){
        let boxs = document.querySelectorAll('a.box');
        if (boxs) {
            for (let index = 0; index < boxs.length; index++) {
                let box = boxs[index];

                let titleCode = box.querySelector('.video-title strong');
                let text = titleCode.innerText;
                let code = text.match(/[A-Za-z]{2,5}-\d{2,5}/)?.at(0);
                if (!code) continue;

                let videoSrc = "https://fivetiu.com/" + code.toLowerCase() + "/preview.mp4";
                let video = document.createElement('video');
                video.style.display = "none";
                video.autoplay = true;
                video.loop = true;
                video.muted = true;
                video.playsinline = true;
                video.dataset.src = videoSrc;
                // video.src =videoSrc;

                let cover = box.querySelector('.cover');
                if (!cover) continue;

                cover.appendChild(video);
            }
        }
    }

    function addMouseListener(){
        // document.addEventListener('DOMContentLoaded', function() {
        const boxs = document.querySelectorAll('.box .cover');
        if (!boxs) return;

        for (let index = 0; index < boxs.length; index++) {
            let cover = boxs[index];

            cover.parentElement.removeAttribute('title');

            cover.addEventListener('mouseenter', function (event) {
                // if (event.target.classList.contains('cover')) {
                const videoContainer = event.target;
                const video = videoContainer.querySelector('video');
                const image = videoContainer.querySelector('img');
                video.style.display = 'block';
                image.style.display = 'none';

                if (!video['src']) {
                    video.src = video.dataset.src;
                }
                image.removeAttribute('alt');
                // }
            });

            cover.addEventListener('mouseleave', function (event) {
                // if (event.target.classList.contains('cover')) {
                const videoContainer = event.target;
                const video = videoContainer.querySelector('video');
                const image = videoContainer.querySelector('img');
                video.style.display = 'none';
                image.style.display = 'block';
                // }
            });
            // });
        }
    }

    async function initVideoListForItem(){
        let all_flag = null;
		try{
			let url = 'http://localhost:10168/allflag';
			
			const response = await fetch(url);
			if(!response.ok){
				throw new Error('HTTP错误! 状态: ${response.status}');
			}
			const result = await response.json();
			if(result.result != 0){
				throw new Error('HTTP错误! 状态: ${result.desc}');
			}
			
			all_flag = result.data;
			
		}catch(error){
			console.log('get all flag error:' + error);
		}
		
		// xxx
        let boxs = document.querySelectorAll('a.box');
        if (boxs) {
            for (let index = 0; index < boxs.length; index++) {
                let box = boxs[index];

                let link = box.href;
                let titleEle = box.querySelector('.video-title');
                let titleStr = titleEle.innerText;
                let titleCode = titleEle.querySelector('strong');
                let text = titleCode.innerText;
                let code = text.match(/[A-Za-z]{2,5}-\d{2,5}/)?.at(0);
                if (!code) continue;

                let cover = box.querySelector('.cover');
                if (!cover) continue;

                let yulan = box.querySelector('.tags.has-addons a[title="预览"]');
                if (yulan) {
                    yulan.addEventListener('click', function (event){
                        let videoSrc = "https://fivetiu.com/" + code.toLowerCase() + "/preview.mp4";
                        let video = document.createElement('video');
                        video.style.display = "none";
                        video.autoplay = true;
                        video.loop = true;
                        video.muted = true;
                        video.playsinline = true;
                        video.dataset.src = videoSrc;
                        // video.src =videoSrc;

                        cover.appendChild(video);

                        addMouseListenerForItem(cover);
                    })
                }

                let yulanTu = box.querySelector('.tags.has-addons a[title="预览图"]');
                if (yulanTu){
                    yulanTu.addEventListener('click', function (event){
                        let imgUrl = "https://blogjav.net/?s=" + code.toLowerCase() + "&jump=auto";
                        // window.open(imgUrl, '_blank');
						popupWindow(imgUrl);
                    })
                }

                let javStoryTu = box.querySelector('.tags.has-addons a[title="综合 JAV资源站"]');
                if (javStoryTu){
                    javStoryTu.addEventListener('click', function (event){
                        // var newUrl = 'http://localhost:10168/site/premovie/index.html?avcode=' + code.toLowerCase() + '&avtitle=' + titleStr + '&avurl=' + link + '&tab=2';
						var newUrl = 'http://localhost:10168/site/premovie/index.html?avcode=' + code.toLowerCase() + '&avtitle=' + titleStr + '&avurl=' + link;
                        // var width = 1420;
                        // var height = 960;
                        // var left = (window.screen.width - width)/2;
                        // var top = (window.screen.height - height)/2;
                        // var popupWindow = window.open(newUrl, '_blank', `left=${left}, top=${top} width=${width}, height=${height}`);
						
						popupWindow(newUrl);
                    })
                }
				
				if(all_flag){
					let flag = all_flag[code];
					if(flag){
						let pinlEle = box.querySelector('.value');
						pinlEle.style = 'color: red';
						// 保存子元素的HTML
						const childrenHTML = pinlEle.innerHTML;
						pinlEle.innerHTML = childrenHTML + ' &nbsp;【【' + flag + '】】';
					}
				}
            }
        }
    }

    function addMouseListenerForItem(cover){
        // #fff-amlfi
        cover.parentElement.removeAttribute('title');

        cover.addEventListener('mouseenter', function (event) {
            // if (event.target.classList.contains('cover')) {
            const videoContainer = event.target;
            const video = videoContainer.querySelector('video');
            const image = videoContainer.querySelector('img');
            video.style.display = 'block';
            image.style.display = 'none';

            if (!video['src']) {
                video.src = video.dataset.src;
            }
            image.removeAttribute('alt');
            // }
        });

        cover.addEventListener('mouseleave', function (event) {
            // if (event.target.classList.contains('cover')) {
            const videoContainer = event.target;
            const video = videoContainer.querySelector('video');
            const image = videoContainer.querySelector('img');
            video.style.display = 'none';
            image.style.display = 'block';
            // }
        });

    }

    //#endregion

    // ******************************************************************************************************************************************************
    //#region 详情页-预告Video
    function createVideoCss_2(){
        // 创建一个新的<style>元素
        const style = document.createElement('style');
        style.type = 'text/css';

        // 添加CSS规则到<style>元素中
        const cssRules = `
      .video-panel .tile-images video {
            z-index: 0;
            transition: transform .2s ease;
            position: absolute;
            top: 0;
            left: 0;
            height: 100%;
            /*-o-object-position: 50% 50%;*/
            /*object-position: 50% 50%;*/
        }
    `;

        if (style.styleSheet) {
            // 对于IE
            style.styleSheet.cssText = cssRules;
        } else {
            // 其他浏览器
            style.appendChild(document.createTextNode(cssRules));
        }

// 将<style>元素添加到文档的<head>中
        document.head.appendChild(style);
    }

    function resetPreVideoBig(){
        var preImgConEles = document.querySelectorAll('.tile-images.tile-small');
        if (!preImgConEles)  return;

        var style1 = document.createElement('style');
        style1.innerHTML = `
          .tile-images-3 {
                display: grid;
                grid-column-gap: 0.2rem;
                -moz-column-gap: .2rem;
                column-gap: 0.2rem;
                grid-row-gap: 0.4rem;
                row-gap: 0.4rem;
                grid-template-columns: repeat(3,minmax(0,1fr));
            }
        `;
        document.body.appendChild(style1);

        for (let index = 0; index < preImgConEles.length; index++) {
            let preImgConEle = preImgConEles[index];

            preImgConEle.classList.remove("tile-images");
            preImgConEle.classList.add("tile-images-3");
        }
    }

    function initVideoList_2(){
        let videoNumbers = document.querySelectorAll('.video-number');
        if (videoNumbers) {
            for (let index = 0; index < videoNumbers.length; index++) {
                let videoNumber = videoNumbers[index];
                let box = videoNumber.parentElement;
                if (!box) continue;

                let text = videoNumber.innerText;
                let code = text.match(/[A-Za-z]{2,5}-\d{2,5}/)?.at(0);
                if (!code) continue;

                let videoSrc = "https://fivetiu.com/" + code.toLowerCase() + "/preview.mp4";
                let video = document.createElement('video');
                // video.style.display = "none";
                video.style = `
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    display: none;
                `;
                video.autoplay = true;
                video.loop = true;
                video.muted = true;
                video.playsinline = true;
                video.dataset.src = videoSrc;
                // video.src =videoSrc;

                box.appendChild(video);
            }
        }
    }

    function addMouseListener_2(){
        // document.addEventListener('DOMContentLoaded', function() {
        let videoNumbers = document.querySelectorAll('.video-number');
        if (!videoNumbers) return;

        for (let index = 0; index < videoNumbers.length; index++) {
            let videoNumber = videoNumbers[index];
            let box = videoNumber.parentElement;
            if (!box) continue;

            box.removeAttribute('title');

            box.addEventListener('mouseenter', function (event) {
                // if (event.target.classList.contains('cover')) {
                const videoContainer = event.target;
                const video = videoContainer.querySelector('video');
                const image = videoContainer.querySelector('img');
                const title = videoContainer.querySelector('.video-title');
                const avnumber = videoContainer.querySelector('.video-number');
                video.style.display = 'block';
                image.style.display = 'none';
                title.style.display = 'none';
                avnumber.style.display = 'none';

                if (!video['src']) {
                    video.src = video.dataset.src;
                }
                image.removeAttribute('alt');
                // }
            });

            box.addEventListener('mouseleave', function (event) {
                // if (event.target.classList.contains('cover')) {
                const videoContainer = event.target;
                const video = videoContainer.querySelector('video');
                const image = videoContainer.querySelector('img');
                const title = videoContainer.querySelector('.video-title');
                const avnumber = videoContainer.querySelector('.video-number');
                video.style.display = 'none';
                image.style.display = 'block';
                title.style.display = 'block';
                avnumber.style.display = 'block';
                // }
            });
            // });
        }
    }

    function addMoivePreVideo(){
        var contDiv = document.getElementsByClassName("preview-images")[0];
        if (!contDiv) return;

        /* 预览video */
        const movieInfo = getMovieInfo();
        if (movieInfo?.movieId) {
            let text = movieInfo.movieId.toLowerCase();
            let code = text.match(/[A-Za-z]{2,5}-\d{2,5}/)?.at(0);
            if (!code) return;;

            let videoSrc = "https://fivetiu.com/" + code.toLowerCase() + "/preview.mp4";

            var preVideo = document.createElement("video");
            preVideo.style = `
                position: absolute;
                top: 0;
                left: 0;
                height: 100%;
            `;
            preVideo.controls = true;
            preVideo.loop = true;
            preVideo.muted = true;
            preVideo.playsinline = true;
            preVideo.src = videoSrc;

            /* 按钮面板 */
            var videoDiv = document.createElement("div");
            videoDiv.style = `
                position: relative;
                padding-top: 35%;
                margin: 20px;
            `;
            videoDiv.appendChild(preVideo);

            /* 插入到页面中 */
            contDiv.parentNode.insertBefore(videoDiv, contDiv);
        }
    }

    //#endregion

    // ******************************************************************************************************************************************************
    //#region BottomPanel

    function addButtonBottomList(){
        // var para = document.createElement("button");
        // var node = document.createTextNode("新的按钮");
        // para.appendChild(node);
        // para.addEventListener("click", testButton01);

        /* 番号范围面板 */
        var ppp1 = document.createElement("p");
        ppp1.innerHTML = `
                    <span>番号范围：</span>
                    <input id="movieId-corp" type="text" style="width: 80px"/>
                    <span> - </span>
                    <input id="movieId-start" type="number" style="width: 60px"/>
                    <span> >>> </span>
                    <input id="movieId-end" type="number" style="width: 60px"/>
                   `;


        /* 提交番号范围 */
        var btnQuery = document.createElement("button");
        btnQuery.appendChild(document.createTextNode("提交"));
        btnQuery.addEventListener("click", queryMovieAddrList);
        ppp1.appendChild(btnQuery);

        var ppp2 = document.createElement("p");
        // ppp2.innerHTML = `
        //             <button onclick="loadMovieInfo()">加载</button>
        //             <button onclick="clearMovieAddrListBottom()">清除</button>
        //            `;
        /* 相似番号 */
        var btnLoad = document.createElement("button");
        btnLoad.style.marginRight = "10px";
        btnLoad.appendChild(document.createTextNode("相同番号"));
        btnLoad.addEventListener("click", loadMovieInfo);
        ppp2.appendChild(btnLoad);

        /* 同类番号 */
        var btnClass= document.createElement("button");
        btnClass.style.marginLeft = "10px";
        btnClass.style.marginRight = "10px";
        btnClass.appendChild(document.createTextNode("同类&主演影片"));
        btnClass.addEventListener("click", queryDetailPageAddrList);
        ppp2.appendChild(btnClass);

        /* 同类番号 */
        var btnClassVideo= document.createElement("button");
        btnClassVideo.style.marginLeft = "10px";
        btnClassVideo.style.marginRight = "10px";
        btnClassVideo.appendChild(document.createTextNode("同类&主演video"));
        btnClassVideo.addEventListener("click", function (){
            //createVideoCss_2();
            resetPreVideoBig();
            initVideoList_2();
            addMouseListener_2();
        });
        ppp2.appendChild(btnClassVideo);

        /* 清除列表 */
        var btnClear= document.createElement("button");
        btnClear.style.marginLeft = "30px";
        btnClear.style.marginRight = "10px";
        btnClear.appendChild(document.createTextNode("清除"));
        btnClear.addEventListener("click", clearMovieAddrListBottom);
        ppp2.appendChild(btnClear);

        /* 播放地址列表 */
        var addrdiv = document.createElement("div");
        addrdiv.className = "movie";
        addrdiv.id = "addr-list-bottom";

        /* 插入到页面中 */
        var element = document.getElementsByClassName("video-detail")[0];
        // element.appendChild(para);
        element.appendChild(ppp2);
        element.appendChild(ppp1)
        element.append(addrdiv);
    }

    function queryMovieAddrList(){
        const movieInfoArr = new Array();
        let corp = document.getElementById("movieId-corp").value;
        let startIndex = parseInt(document.getElementById("movieId-start").value);
        let endIndex = parseInt(document.getElementById("movieId-end").value);
        let len = endIndex - startIndex;

        for (var i=0; i<=len; i++) {
            let movieInfo = getMovieInfo();
            let index = startIndex + i;
            movieInfo.movieId = corp + "-" + padNumber(index, 3);
            movieInfoArr[i] = movieInfo
            if (movieInfoArr[i]?.movieId) {
                addVideoAddrElementBottom("sreach_addr", movieInfo);
                getVideoURL_2(movieInfoArr[i]).then((movieInfo) => {
                    if (!movieInfo.videoURL) return;

                    console.log(movieInfo.videoURL)
                    updateVideoAddrElement("sreach_addr", movieInfo);
                });
            }
        }
    }

    function clearMovieAddrListBottom(){
        var ddd = document.getElementById("addr-list-bottom");
        ddd.innerHTML = "";
    }

    function addVideoAddrElementBottom(pre_id, movieInfo) {
        var para = document.createElement("p");

        const newCheckbox = document.createElement('input');
        newCheckbox.type = 'checkbox'; // 设置类型为checkbox

        var addr = document.createElement("a");
        addr.id = pre_id + "_" + movieInfo.movieId;
        addr.href = movieInfo.videoURL;
        addr.target = "_blank";
        var text = document.createTextNode(movieInfo.videoURL);
        addr.append(text);

        var title = document.createElement("a");
        title.style.color = "#e5a555"
        title.href = movieInfo.webURL;
        title.target = "_blank";
        var text = document.createTextNode("***【" + movieInfo.movieId + "】***\t");
        title.append(text);

        para.appendChild(newCheckbox);
        para.appendChild(title)
        para.appendChild(addr);

        var element = document.getElementById("addr-list-bottom");
        if (element){
            element.appendChild(para);
        }
    }

    function queryDetailPageAddrList(){
        const detailMovieInfoArr = new Array();
        let elements = $('.video-number');
        for(var i=0; i<elements.length; i++) {
            let element = elements[i];
            let text = element.innerText;
            let code = text.match(/[A-Za-z]{2,5}-\d{2,5}/)?.at(0);
            if (!code) continue;

            let movieInfo = createMovieInfo();
            movieInfo.movieId = code;
            movieInfo.webURL = element.parentNode.href;
            detailMovieInfoArr.push(movieInfo);
        }

        if (detailMovieInfoArr.length <= 0){
            return;
        }

        for(var j=0; j<detailMovieInfoArr.length; j++){

            var movieInfo = detailMovieInfoArr[j];
            if (movieInfo?.movieId){
                addVideoAddrElementBottom("detail_addr", movieInfo);
                getVideoURL_2(movieInfo).then((movieInfo) => {
                    if (!movieInfo.videoURL) return;

                    console.log(movieInfo.videoURL);
                    updateVideoAddrElement("detail_addr", movieInfo);
                });
            }
        }
    }

    //#endregion

    // *******************************************************************************************************8
    //#region TopPanel

    function addTopButtonList(){
        // #fff-tbl
        var ppp2 = document.createElement("p");
        // ppp2.innerHTML = `
        //             <button onclick="loadMovieInfo()">加载</button>
        //             <button onclick="clearMovieAddrListBottom()">清除</button>
        //            `;

        /* 查询播放地址 */
        var btnLoad = document.createElement("button");
        btnLoad.style.marginRight = "10px";
        btnLoad.appendChild(document.createTextNode("加载"));
        btnLoad.addEventListener("click", queryMoviePageAddrList);
        ppp2.appendChild(btnLoad);

        /* 清除列表 */
        var btnClear= document.createElement("button");
        btnClear.style.marginLeft = "10px";
        btnClear.style.marginRight = "10px";
        btnClear.appendChild(document.createTextNode("清除"));
        btnClear.addEventListener("click", clearMovieAddrListTop);
        ppp2.appendChild(btnClear);

        /* 每行显示数 */
        var inputBoxNumber = document.createElement("input");
        inputBoxNumber.style.marginLeft = "50px";
        inputBoxNumber.style.marginRight = "5px";
        inputBoxNumber.style.width = "60px";
        inputBoxNumber.id = "page-row-number";
        inputBoxNumber.type = "number";
        inputBoxNumber.value = 2;
        ppp2.appendChild(inputBoxNumber);

        var btnBoxNumber = document.createElement("button");
        btnBoxNumber.style.marginLeft = "5px";
        btnBoxNumber.style.marginRight = "10px";
        btnBoxNumber.appendChild(document.createTextNode("每行显示数"));
        btnBoxNumber.addEventListener("click", resetPageRowNumber);
        ppp2.appendChild(btnBoxNumber);

        /* 列表中增加播放按钮 */
        var btnPlay= document.createElement("button");
        btnPlay.style.marginLeft = "10px";
        btnPlay.style.marginRight = "10px";
        btnPlay.appendChild(document.createTextNode("list播放"));
        btnPlay.addEventListener("click", addPreplayButtonList);
        ppp2.appendChild(btnPlay);

        /* 列表中增加播放按钮 */
        var btnPreVideo= document.createElement("button");
        btnPreVideo.style.marginLeft = "10px";
        btnPreVideo.style.marginRight = "10px";
        btnPreVideo.appendChild(document.createTextNode("list预告"));
        btnPreVideo.addEventListener("click", function (){
            createVideoCss();
            // initVideoList();
            // addMouseListener();

            initVideoListForItem();
        });
        ppp2.appendChild(btnPreVideo);

        /* 删除蒙版 */
        var btnDelPlayPanel= document.createElement("button");
        btnDelPlayPanel.style.marginLeft = "10px";
        btnDelPlayPanel.style.marginRight = "10px";
        btnDelPlayPanel.appendChild(document.createTextNode("删除蒙版"));
        btnDelPlayPanel.addEventListener("click", delPlayPanel);
        ppp2.appendChild(btnDelPlayPanel);

        /* 获取预览图地址 */
        var btnCopyTitle= document.createElement("button");
        btnCopyTitle.style.marginLeft = "10px";
        btnCopyTitle.style.marginRight = "10px";
        btnCopyTitle.appendChild(document.createTextNode("标题"));
        btnCopyTitle.addEventListener("click", async function (){
            try {
                var classObj = copyAvClass(false);

                var titleStrS = copyAvTitleS(false);
                var nvYan = parseYanYuan(classObj.yanYuan);
                // navigator.clipboard.writeText(titleStrS + nvYan);
				copyTextToClipboard(titleStrS + nvYan);

                console.log('-------复制标题成功！！！！！！！！！');
            }catch (err){
                console.error('-------复制标题失败: ', err);
            }

        });
        ppp2.appendChild(btnCopyTitle);

        /* 获取预览图地址 */
        var btnCopyUrl= document.createElement("button");
        btnCopyUrl.style.marginLeft = "10px";
        btnCopyUrl.style.marginRight = "10px";
        btnCopyUrl.appendChild(document.createTextNode("弹窗"));
        btnCopyUrl.addEventListener("click", function (){
            // copyAvUrl();
			
			let movieInfo = getMovieInfo();
            if (movieInfo.movieId){
                let avUrl = 'http://localhost:10168/site/premovie/index.html?avcode=' + movieInfo.movieId.toLowerCase();
                popupWindow(avUrl);
            }
        });
        ppp2.appendChild(btnCopyUrl);

        /* 获取预览图地址 */
        var btnCopyCover= document.createElement("button");
        btnCopyCover.style.marginLeft = "10px";
        btnCopyCover.style.marginRight = "10px";
        btnCopyCover.appendChild(document.createTextNode("封面"));
        btnCopyCover.addEventListener("click", async function (){
            try {
                copyCoverImage();

                console.log('-------复制图片成功！！！！！！！！！');
            }catch (err){
                console.error('-------复制图片失败: ', err);
            }

        });
        ppp2.appendChild(btnCopyCover);

        /* 获取预览图地址 */
        var btnCopyPreimage= document.createElement("button");
        btnCopyPreimage.style.marginLeft = "10px";
        btnCopyPreimage.style.marginRight = "10px";
        btnCopyPreimage.appendChild(document.createTextNode("预览图"));
        // btnCopyPreimage.addEventListener("click", copyPreimageAddr);
        btnCopyPreimage.addEventListener("click", function (){
            let movieInfo = getMovieInfo();
            if (movieInfo.movieId){
                let imgUrl = "https://blogjav.net/?s=" + movieInfo.movieId + "&jump=auto";
                // window.open(imgUrl, '_blank');
				popupWindow(imgUrl);
            }
        });
        ppp2.appendChild(btnCopyPreimage);

        /* 综合复制 */
        var btnPreview= document.createElement("button");
        btnPreview.style.marginLeft = "10px";
        btnPreview.style.marginRight = "10px";
        btnPreview.appendChild(document.createTextNode("预告片"));
        btnPreview.addEventListener("click", function (){
            copyPreviewAddr(true);
        });
        ppp2.appendChild(btnPreview);

        /* 综合复制 */
        var btnCopyAll2= document.createElement("button");
        btnCopyAll2.style.marginLeft = "10px";
        btnCopyAll2.style.marginRight = "10px";
        btnCopyAll2.appendChild(document.createTextNode("综合复制2"));
        btnCopyAll2.addEventListener("click", async function (){
            try {
                var classObj = copyAvClass(false)

                var titleStrL = copyAvTitleL(false);
                var avUrl = copyAvUrl(false);
                var preimgAddr = copyPreimageAddr(false);
                var prevideoAddr = copyPreviewAddr(false);
                var zongHe = "【标  题】：" + titleStrL + "\r\n【系  列】：" + classObj.xilie + "\r\n【类  别】：" + classObj.leiBe + "\r\n【演  员】：" + classObj.yanYuan + "\r\n【页  面】：" + avUrl + "\r\n【预览图】：" + preimgAddr + "\r\n【预告片】：" + prevideoAddr + "\r\n";
                navigator.clipboard.writeText(zongHe);

                await sleep(1000);

                var titleStrS = copyAvTitleS(false);
                var nvYan = parseYanYuan(classObj.yanYuan);
                navigator.clipboard.writeText(titleStrS + nvYan);

                console.log('-------复制成功！！！！！！！！！');
            }catch (err){
                console.error('-------复制失败: ', err);
            }

        });
        ppp2.appendChild(btnCopyAll2);
		
		/* xxx */
        var btnMissAV= document.createElement("button");
        btnMissAV.style.marginLeft = "10px";
        btnMissAV.style.marginRight = "10px";
        btnMissAV.appendChild(document.createTextNode("MisAV"));
        // btnMissAV.addEventListener("click", copyPreimageAddr);
        btnMissAV.addEventListener("click", function (){
            let movieInfo = getMovieInfo();
            if (movieInfo.movieId){
                let imgUrl = "https://missav2.one/cn/" + movieInfo.movieId.toLowerCase() ;
                // window.open(imgUrl, '_blank');
                popupWindow(imgUrl);
            }
        });
        ppp2.appendChild(btnMissAV);

        /* 按钮面板 */
        var buttondiv = document.createElement("div");
        buttondiv.style.backgroundColor = "#3272dc";
        buttondiv.style.padding = "0.8rem";
        buttondiv.style.margin = 5;
        buttondiv.appendChild(ppp2);

        /* 地址面板 */
        var addrdiv = document.createElement("div");
        addrdiv.style.backgroundColor = "#eee";
        addrdiv.style.display = "block";
        addrdiv.id = "addr-list-top";

        /* 插入到页面中 */
        var element = document.getElementsByClassName("container")[0];
        if (element){

            element.insertBefore(addrdiv, element.firstChild);
            element.insertBefore(buttondiv, addrdiv);
        }
    }

    function addPreplayButtonList(){

        var eleList = document.querySelectorAll(".box");
        for (let i = 0; i < eleList.length; i++) {
            var ele = eleList[i];

            const btnDev = ele.querySelector(".tags.has-addons");
            var avidStg = ele.querySelector(".video-title strong");

            if (!btnDev || !avidStg){
                continue;
            }

            var avid = avidStg.textContent;
            if (avid){
                var movieInfo = createMovieInfo();
                movieInfo.movieId = avid;

                if (movieInfo?.movieId){

                    getVideoURL_2(movieInfo).then((movieInfo) => {
                        if (!movieInfo.videoURL) return;

                        console.log(movieInfo.videoURL);

                        // var playBtn = document.createElement("a");
                        // playBtn.title = "播放";
                        // playBtn.style = "margin-right: 3px;background-color:#b2a333;";
                        // playBtn.textContent = "播放";
                        // playBtn.target = "_blank";
                        // playBtn.href = movieInfo.videoURL;

                        var playBtn = document.createElement("button");
                        playBtn.title = "播放";
                        playBtn.style = "margin-right: 3px;background-color:#b2a333;";
                        playBtn.textContent = "播放";
                        playBtn.addEventListener('click', function (evt){
                            evt.preventDefault();
                            copyTextToClipboard(movieInfo.videoURL);
                        })

                        const newCheckbox = document.createElement('input');
                        newCheckbox.type = 'checkbox'; // 设置类型为checkbox

                        if (btnDev){
                            btnDev.appendChild(playBtn);
                            btnDev.appendChild(newCheckbox);
                        }
                    });
                }
            }



        }
    }

    function clearMovieAddrListTop(){
        var ddd = document.getElementById("addr-list-top");
        ddd.innerHTML = "";
    }

    function queryMoviePageAddrList(){
        // document.getElementById("demo").innerHTML=Date();
        const movieInfoArr = new Array();
        //let elements = document.getElementsByClassName("sav-id infoFirst");
        let elements = $('.video-title strong');
        for(var i=0; i<elements.length; i++){
            let element = elements[i];
            let text = element.innerText;
            let code = text.match(/[A-Za-z]{2,5}-\d{2,5}/)?.at(0);
            if (!code) continue;

            let movieInfo = createMovieInfo();
            movieInfo.movieId = code;
            movieInfo.webURL = element.parentNode.parentNode.href;
            movieInfoArr[i] = movieInfo;
            if (movieInfoArr[i]?.movieId) {
                addVideoAddrElementTop("home_addr", movieInfo);
                getVideoURL_2(movieInfoArr[i]).then((movieInfo) => {
                    if (!movieInfo.videoURL) return;

                    console.log(movieInfo.videoURL);
                    updateVideoAddrElement("home_addr", movieInfo);
                });
            }
        }
    }

    function addVideoAddrElementTop(pre_id, movieInfo) {
        var para = document.createElement("p");

        const newCheckbox = document.createElement('input');
        newCheckbox.type = 'checkbox'; // 设置类型为checkbox

        var addr = document.createElement("a");
        addr.id = pre_id + "_" + movieInfo.movieId;
        addr.href = movieInfo.videoURL;
        addr.target = "_blank";
        var text = document.createTextNode(movieInfo.videoURL);
        addr.append(text);

        var title = document.createElement("a");
        title.style.color = "#e5a555"
        title.href = movieInfo.webURL;
        title.target = "_blank";
        var text = document.createTextNode("***【" + movieInfo.movieId + "】***\t");
        title.append(text);

        para.appendChild(newCheckbox);
        para.appendChild(title)
        para.appendChild(addr);

        var element = document.getElementById("addr-list-top");
        if (element){
            element.appendChild(para);
        }
    }



    function resetPageRowNumber(){
        var numberElement = document.getElementById("page-row-number");
        if (!numberElement) return;

        var element = document.getElementsByClassName("movie-list")[0];
        if (!element) return;

        var number = parseInt(numberElement.value);
        element.style.gridTemplateColumns = "repeat(" + number + ",minmax(0,1fr))";
    }

    function delPlayPanel(){
        // 查找具有类名'cover-container'的元素
        var img = document.querySelector('.column.column-video-cover img');
        var container = document.querySelector('.column.column-video-cover');
        if (container){
            // 获取所有子元素
            var children = container.children;
            // 遍历子元素
            for (var i = children.length - 1; i >= 0; i--) { // 从后往前遍历以避免索引问题
                if (children[i].classList.contains('cover-container')) {
                    // 如果包含，则移除该子元素
                    container.removeChild(children[i]);
                }
            }

            container.appendChild(img);
        }

        // if (container) {
        //     // 删除该元素的class属性
        //     container.removeAttribute('class');
        //
        //     // 获取所有子元素
        //     var children = container.children;
        //
        //     // 遍历子元素
        //     for (var i = children.length - 1; i >= 0; i--) { // 从后往前遍历以避免索引问题
        //         // 检查子元素是否包含类名'play-button'
        //         if (children[i].classList.contains('play-button')) {
        //             // 如果包含，则移除该子元素
        //             container.removeChild(children[i]);
        //         }
        //     }
        // }
    }

    function copyPreimageAddr(isCopy=true){
        var imgElement = document.getElementById('javRealImg');
        if (imgElement) {
            var src = imgElement.src;
            // 现在src变量包含了img元素的src属性值

            if (src && src.startsWith('https://')) {
                // 第一步：替换"images"为"show"
                src = src.replace('images', 'show');

                // 第二步：移除第一个出现的"img"后跟两个数字
                // 注意：这个正则表达式假设"img"后跟的恰好是两个数字，且这些数字是连续的
                src = src.replace(/img\d{2}\./, '');

                // 现在src变量已经按照要求修改过了
                console.log("预览图页面地址：" + src); // 输出修改后的src值
                //copyTextToClipboard(src);
                if (isCopy){
                    navigator.clipboard.writeText(src);
                }
                return src;
            }
        }
    }

    function copyPreviewAddr(isCopy=true){
        var videoElement = document.querySelector('#preview-video source');
        if (videoElement) {
            var src = videoElement.src;

            console.log("预告片地址：" + src); // 输出修改后的src值
            //copyTextToClipboard(src);
            if (isCopy){
                navigator.clipboard.writeText(src);
            }
            return src;
        }
    }

    function copyAvTitleS(isCopy=true){
        var titleStr = "";

        var titleEles = document.querySelectorAll('.title.is-4 strong');
        // titleEles.forEach(function (item){
        //     titleStr += item.textContent + "==";
        // });
        if (titleEles && titleEles.length >= 2){
            titleStr += titleEles[0].textContent.trim();
            const selected = getSelectedText();
            if (selected) {
                titleStr += " " + selected.trim();
            } else {
                titleStr += " " + concatenateChineseCharacters_2(titleEles[1].textContent);
            }


            //copyTextToClipboard(titleStr);
            if (isCopy){
                navigator.clipboard.writeText(titleStr);
            }
            return titleStr;
        }
    }

    function copyAvTitleL(isCopy=true){
        var titleStr = "";

        var titleEles = document.querySelectorAll('.title.is-4 strong');
        if (titleEles && titleEles.length >= 2){
            titleStr += titleEles[0].textContent;
            titleStr += " " + titleEles[1].textContent;

            //copyTextToClipboard(titleStr);
            if (isCopy){
                navigator.clipboard.writeText(titleStr);
            }
            return titleStr;
        }
    }

    function copyAvClass(isCopy=true){
        // 使用querySelectorAll获取所有匹配的strong标签
        const strongTags = document.querySelectorAll('.panel.movie-panel-info strong');
        let xilie = null;
        let leiBe = null;
        let yanYuan = null;

        // 使用for循环遍历这些strong标签
        for (let i = 0; i < strongTags.length; i++) {
            // 获取当前strong标签
            const strongTag = strongTags[i];
            const strongText = strongTag.textContent.trim();

            // 检查strong标签的文本内容是否等于"类别"（注意：处理可能的空格）
            if (strongText === '系列:') {
                // 获取strong标签的同级元素
                let destSpan = getSpanEle(strongTag);
                if (destSpan){
                    xilie = destSpan.innerText;
                }
            }

            if (strongText === '類別:'){
                let destSpan = getSpanEle(strongTag);
                if (destSpan){
                    leiBe = destSpan.innerText;
                }
            }

            if (strongText === '演員:'){
                let destSpan = getSpanEle(strongTag);
                if (destSpan){
                    yanYuan = destSpan.innerText;
                }
            }
        }

        function getSpanEle(strongTag){
            let sibling = strongTag.nextSibling;
            let destSpan = null

            // 遍历同级元素直到找到span或到达同级元素的末尾
            while (sibling) {
                // 检查是否到达了同级span标签
                if (sibling.nodeType === Node.ELEMENT_NODE && sibling.tagName === 'SPAN') {
                    // 如果找到了span标签，则执行相应的操作
                    destSpan = sibling;
                    break; // 找到后退出循环
                }
                // 否则，继续遍历下一个同级元素
                sibling = sibling.nextSibling;
            }

            return destSpan;
        }

        return {xilie, leiBe, yanYuan};
    }

    function copyAvUrl(isCopy=true){
        var currentURL = window.location.href;

        //copyTextToClipboard(currentURL);
        if (isCopy){
            navigator.clipboard.writeText(currentURL);
        }
        return currentURL;
    }

    function copyCoverImage(){
        var img = document.querySelector('.column-video-cover img');
        if (img){
            img.crossOrigin = 'javdb367.com';
            // 创建一个新的Image对象，以便我们可以获取它的完整URL（包括跨域处理）
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');

            // 设置canvas的大小与图片相同
            canvas.width = img.naturalWidth;
            canvas.height = img.naturalHeight;

            // 将图片绘制到canvas上
            ctx.drawImage(img, 0, 0);

            // 将canvas转换为Blob对象
            canvas.toBlob(async (blob) => {
                try {
                    // 创建一个File对象
                    const item = new ClipboardItem({[blob.type]: blob});
                    //const item = new ClipboardItem({ "image/png": blob });

                    // 写入剪贴板
                    await navigator.clipboard.write([item]);
                    console.log('图片已复制到剪贴板');
                } catch (err) {
                    console.error('复制失败:', err);
                }
            }, 'image/png'); // 注意：这里我们假设将图片转换为PNG格式
        }
    }
	
	function copyTextToClipboard(text) {
		var textArea = document.createElement("textarea");
		textArea.value = text;
		document.body.appendChild(textArea);
		textArea.focus();
		textArea.select();
		
		try {
			var successful = document.execCommand('copy');
			var msg = successful ? 'successful' : 'unsuccessful';
			console.log('Fallback: Copying text command was ' + msg);
		} catch (err) {
			console.error('Fallback: Oops, unable to copy', err);
		}
		
		document.body.removeChild(textArea);
	}


    //#endregion

    // ******************************************************************************************************************************************************
    //#region BigReimage

    function addReimageButton(){
        

        /* 插入到页面中 */
        var element = document.getElementsByClassName("preview-images")[0];
        if (element){
			var ppp2 = document.createElement("p");
			// ppp2.innerHTML = `
			//             <button onclick="loadMovieInfo()">加载</button>
			//             <button onclick="clearMovieAddrListBottom()">清除</button>
			//            `;

			/* 大预览图 */
			var btnPreImg= document.createElement("button");
			btnPreImg.style.marginLeft = "30px";
			btnPreImg.style.marginRight = "10px";
			btnPreImg.appendChild(document.createTextNode("大预览图"));
			btnPreImg.addEventListener("click", resetBigPreimg);
			ppp2.appendChild(btnPreImg);

			/* 按钮面板 */
			var buttondiv = document.createElement("div");
			buttondiv.style.backgroundColor = "#eee";
			buttondiv.style.padding = "20px"
			buttondiv.appendChild(ppp2);
			
            element.parentNode.insertBefore(buttondiv, element);
        }
    }

    function resetBigPreimg(){
        var preImgConEle = document.getElementsByClassName("preview-images")[0];
        if (preImgConEle){
            var style1 = document.createElement('style');
            style1.innerHTML = `
              .tile-images-2 {
                    display: grid;
                    grid-column-gap: 0.2rem;
                    -moz-column-gap: .2rem;
                    column-gap: 0.2rem;
                    grid-row-gap: 0.4rem;
                    row-gap: 0.4rem;
                    grid-template-columns: repeat(2,minmax(0,1fr));
                }
            `;
            document.body.appendChild(style1);

            preImgConEle.classList.remove("tile-images");
            preImgConEle.classList.add("tile-images-2");
        }

        var preImgEles = $(".preview-images img");
        if (preImgEles && preImgEles.length > 0){
            // var style2 = document.createElement('style');
            // style2.innerHTML = `
            //   .img-2 {
            //         height: auto;
            //         max-width: 250%;
            //         width: 500px
            //     }
            // `;
            // document.body.appendChild(style2);

            for(var i=0; i<preImgEles.length; i++){
                var preImgEle = preImgEles[i];
                //console.log(preImgEle);

                //preImgEle.classList.add("img-2");
                preImgEle.src = preImgEle.parentNode.href;
            }
        }
    }

    //#endregion

    // ******************************************************************************************************************************************************
    //#region Cili

    function addCiliButton(){
		var element = document.getElementsByClassName("magnet-links")[0];
        if (!element){
            return;
        }
		
        var ppp2 = document.createElement("p");
        // ppp2.innerHTML = `
        //             <button onclick="loadMovieInfo()">加载</button>
        //             <button onclick="clearMovieAddrListBottom()">清除</button>
        //            `;

        /* 磁力搜索 */
        var btnCiliSreach = document.createElement("button");
        btnCiliSreach.style.marginLeft = "30px";
        btnCiliSreach.style.marginRight = "10px";
        btnCiliSreach.appendChild(document.createTextNode("磁力猫搜索"));
        btnCiliSreach.addEventListener("click", function (event){
            var movieInfo = getMovieInfo();
            if (movieInfo.movieId){
                var code = movieInfo.movieId;
                // var newCode = code.toLowerCase().replace("-", "%20");
				var newCode = code.toUpperCase();

                var ciliUrl = "https://xiongmaoto.top/?searchstr=" + newCode;
                // window.open(ciliUrl);
				popupWindow(ciliUrl, 900, 1100);
            }
        });
        ppp2.appendChild(btnCiliSreach);

        /* 磁力搜索 */
        var btnCiliSreach2 = document.createElement("button");
        btnCiliSreach2.style.marginLeft = "30px";
        btnCiliSreach2.style.marginRight = "10px";
        btnCiliSreach2.appendChild(document.createTextNode("磁力搜索2"));
        btnCiliSreach2.addEventListener("click", function (event){
            var movieInfo = getMovieInfo();
            if (movieInfo.movieId){
                var code = movieInfo.movieId;
                // var newCode = code.toLowerCase().replace("-", "%20");
				var newCode = code.toUpperCase();

                var ciliUrl = "https://qjkkuqvc.2048173.xyz/search-" + newCode + "-0-1-1.html";
                window.open(ciliUrl);
            }
        });
        ppp2.appendChild(btnCiliSreach2);

        /* 按钮面板 */
        var buttondiv = document.createElement("div");
        buttondiv.style.backgroundColor = "#eee";
        buttondiv.style.padding = "20px"
        buttondiv.appendChild(ppp2);

        /* 插入到页面中 */
        element.parentNode.insertBefore(buttondiv, element);

    }

    function ciliSreach(){
        var movieInfo = getMovieInfo();
        if (movieInfo.movieId){
            var code = movieInfo.movieId;
            var newCode = code.replace("-", " ");
            GM_setClipboard(newCode);
            //var ciliUrl = "https://xiongmaoto.top/search?keyword=" + newCode + "&sos=relevance&sofs=all&sot=all&soft=all&som=exact&p=1";
            var ciliUrl = "https://xiongmaoto.top";
            window.open(ciliUrl);
        }
    }

    //#endregion





    // ******************************************************************************************************************************************************


})();
